﻿//-----------------------------------------------------------------------
// <copyright file="ReportReader.cs">
//     Copyright (c) Nicole Calinoiu. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Xml;

using Microsoft.FxCop.Sdk;

namespace Bordecal.FxCop.Sdk.Testing
{
	/// <summary>
	/// Helper class used to read FxCop reports.
	/// </summary>
	internal static class ReportReader
	{
		#region Methods

		internal static IList<Issue> ExtractIssues(string reportPath)
		{
			return ReportReader.ExtractIssues(new string[] { reportPath });
		}

		internal static IList<Issue> ExtractIssues(IEnumerable<string> reportPaths)
		{
			IList<Issue> issues = new List<Issue>();
			foreach (string reportPath in reportPaths)
			{
				XmlDocument report = new XmlDocument();
				report.Load(reportPath);
				
				ReportReader.ExtractNamespaceIssues(report.DocumentElement.SelectNodes(@"Namespaces/Namespace"), null, issues);
				ReportReader.ExtractAssemblyIssues(report.DocumentElement.SelectNodes(@"Targets/Target"), issues);
			}

			return issues;
		}

		private static void ExtractNamespaceIssues(XmlNodeList namespaceNodes, Module parentModule, IList<Issue> issues)
		{
			foreach (XmlElement namespaceNode in namespaceNodes)
			{
				Namespace nameSpace = new Namespace(parentModule, namespaceNode);
				ReportReader.ExtractMessageIssues(namespaceNode, nameSpace, issues);

				foreach (XmlElement typeNode in namespaceNode.SelectNodes(@"Types/Type"))
				{
					Type type = new Type(nameSpace, typeNode);
					ReportReader.ExtractMessageIssues(typeNode, type, issues);

					foreach (XmlElement memberNode in typeNode.SelectNodes(@"Members/Member"))
					{
						Member member = new Member(type, memberNode);
						ReportReader.ExtractMessageIssues(memberNode, member, issues);

						foreach (XmlElement accessorNode in memberNode.SelectNodes(@"Accessors/Accessor"))
						{
							Member accessor = new Member(member, accessorNode);
							ReportReader.ExtractMessageIssues(accessorNode, accessor, issues);
						}
					}
				}
			}
		}

		private static void ExtractAssemblyIssues(XmlNodeList targetNodes, IList<Issue> issues)
		{
			foreach (XmlElement assemblyNode in targetNodes)
			{
				Assembly assembly = new Assembly(assemblyNode);
				ReportReader.ExtractMessageIssues(assemblyNode, assembly, issues);

				foreach (XmlElement moduleNode in assemblyNode.SelectNodes(@"Modules/Module"))
				{
					Module module = new Module(assembly, moduleNode);
					ReportReader.ExtractMessageIssues(moduleNode, module, issues);
					ReportReader.ExtractNamespaceIssues(moduleNode.SelectNodes(@"Namespaces/Namespace"), module, issues);
				}

				foreach (XmlElement resourceNode in assemblyNode.SelectNodes(@"Resources/Resource"))
				{
					Resource resource = new Resource(assembly, resourceNode);
					ReportReader.ExtractMessageIssues(resourceNode, resource, issues);
				}
			}
		}

		private static void ExtractMessageIssues(XmlNode parentNode, Target parent, IList<Issue> issues)
		{
			foreach (XmlElement messageNode in parentNode.SelectNodes(@"Messages/Message"))
			{
				Message message = new Message(parent, messageNode);
				foreach (XmlElement issueNode in messageNode.SelectNodes(@"Issue"))
				{
					issues.Add(new Issue(message, issueNode));
				}
			}
		}

		#endregion
	}
}